模拟实现JS call方法

一句话介绍call

A.call(B)
A的方法借给B, B临时借用A的方法来完成B的需求

为什么要使用call/apply/bind?

使用ES5的继承,你需要新声明一个函数来承载这些方法,那么使用call就可以通过改变上下文
来临时借用方法.更加的方便和灵活.

实现思路

1. 给B函数添加一个方法,值为A函数
2. 执行B函数中的A函数
3. 删除B函数中的A函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Function.prototype.myCall = function (context) {
context.tempFn = this //A发起的调用,所以this指向A
context.tempFn()
delete context.tempFn
}

var B = {
value: 10,
}

function A () {
document.write(this.value)
}

A.myCall(B) // 10

添加形参和返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Function.prototype.myCall2 = function (context) {
context.tempFn = this //A发起的调用,所以this指向A
var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']')
}
// console.log(args) // (2) ["arguments[1]", "arguments[2]"]
var result = eval('context.tempFn(' + args +')')
//在eval中,args 自动调用 args.toString()方法
//最终结果相当于context.fn(arguments[1], arguments[2])
delete context.tempFn
return result
}

var B = {
value: 10,
}

function A (name, age) {
document.write(name)
document.write(age)
document.write(this.value)
return {
value: this.value,
name: name,
age: age
}
}


console.log('返回值', A.myCall2(B, '小明', 18))
// Object {
// value: 10,
// name: '小明',
// age: 18
// }

注意

1.this的参数可以传null,传null视为指向window

总结

1. Demo

-------------本文结束 感谢您的阅读-------------